#include <iostream>

using std::cout;
using std::endl;

class Point
{
public:
    Point(int ix = 0, int iy = 0)
    : _ix(ix)
    , _iy(iy)
    {
        cout << "Point(int = 0, int = 0)" << endl;
    }

    Point(const Point &rhs)
    : _ix(rhs._ix)
    , _iy(rhs._iy)
    {
        cout << "Point(const Point &)" << endl;
    }

    //this存在与每一个非静态的成员函数的第一个参数的位置
    //特点：this是一个指针常量 * const
    //作用：用来记录对象本身的地址
    void print(/* Point  * const this */)
    {
        /* this->_ix = 100;//ok */
        /* this = nullptr;//error,不能改变指向 */
        /* this = 0x7fff123456;//error */
        cout << "(" << this->_ix 
             << ", " << this->_iy
             << ")" << endl;
    }

    //Q1:赋值运算符函数参数中的引用符号能去掉吗？
    //A1:不能去掉，否则在形参与实参结合的时候会调用拷贝构造
    //函数，多执行一次函数调用，就损失效率(注意：没有栈溢出)
    //
    //Q2：赋值运算符函数参数中的const能去掉吗？
    //A2:如果传递的是右值，那么非const左值引用不能绑定到右值
    //与之前研究的拷贝构造函数参数中的const不能去掉的原因一致
    //对于右值传递会有问题
    //
    //Q3：赋值运算符函数的返回类型中的引用可以去掉吗？
    //A3:不能去掉，如果去掉，那么赋值运算符函数的返回类型是
    //一个类类型，那么在执行return语句的时候，会调用拷贝
    //构造函数，所以会损失效率
    //
    //Q4：赋值运算符函数的返回类型可以是空吗？
    //A4: 连等

    //pt2 = pt1
    //默认情况下，编译器会自动生成赋值运算符函数
    Point &operator=(const Point &rhs)
    {
        cout << "Point &operator=(const Point &)" << endl;
        this->_ix =  rhs._ix;//赋值
        _iy = rhs._iy;

        return *this;
    }

    ~Point()
    {
        cout << "~Point()" << endl;
    }

private:
    int _ix;
    int _iy;
};

void test()
{
    int a = 10;
    int b = 20;
    int c = 30;
    c = b = a;//赋值, int = int
    cout << "a = " << a << endl
         << "b = " << b << endl;

    cout << endl;
    Point pt1(1, 2);//栈对象
    cout << "pt1 = ";
    pt1.print();

    cout << endl;
    Point pt2(3, 4);//栈对象
    cout << "pt2 = ";
    pt2.print();

    cout << endl;
    Point pt3 = pt1;//初始化

    cout << endl;
    //Point &operator=(const Point rhs)
    //const Point rhs = pt1
    //
    //Point(const Point &rhs)
    pt3 = pt2 = pt1;//赋值,Point = Point
    /* pt2.operator=(pt1); */
    cout << "pt1 = ";
    pt1.print();
    cout << "pt2 = ";
    pt2.print();
}

int main(int argc, char **argv)
{
    test();
    return 0;
}

